import os
import pickle
import zipfile
import xlwt
import json
import shutil
from datetime import datetime
from config.settings import PATH_CONFIG

class FileManager:
    """文件管理类"""
    
    @staticmethod
    def ensure_directory(path):
        """确保目录存在，如果不存在则创建"""
        os.makedirs(path, exist_ok=True)
        return path
    
    @staticmethod
    def save_pickle(data, filepath):
        """保存数据到pickle文件"""
        try:
            FileManager.ensure_directory(os.path.dirname(filepath))
            with open(filepath, 'wb') as f:
                pickle.dump(data, f)
            return True
        except Exception as e:
            print(f"保存pickle文件失败: {e}")
            return False
    
    @staticmethod
    def load_pickle(filepath, default=None):
        """从pickle文件加载数据"""
        try:
            with open(filepath, 'rb') as f:
                return pickle.load(f)
        except Exception as e:
            print(f"加载pickle文件失败: {e}")
            return default
    
    @staticmethod
    def save_json(data, filepath, indent=4):
        """保存数据到JSON文件"""
        try:
            FileManager.ensure_directory(os.path.dirname(filepath))
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=indent)
            return True
        except Exception as e:
            print(f"保存JSON文件失败: {e}")
            return False
    
    @staticmethod
    def load_json(filepath, default=None):
        """从JSON文件加载数据"""
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                return json.load(f)
        except Exception as e:
            print(f"加载JSON文件失败: {e}")
            return default
    
    @staticmethod
    def get_file_size(filepath):
        """获取文件大小（MB）"""
        try:
            size_bytes = os.path.getsize(filepath)
            return size_bytes / (1024 * 1024)  # 转换为MB
        except:
            return 0
    
    @staticmethod
    def get_directory_size(directory):
        """获取目录大小（MB）"""
        total_size = 0
        for dirpath, dirnames, filenames in os.walk(directory):
            for filename in filenames:
                filepath = os.path.join(dirpath, filename)
                total_size += os.path.getsize(filepath)
        return total_size / (1024 * 1024)  # 转换为MB
    
    @staticmethod
    def cleanup_old_files(directory, days_old=30):
        """清理指定天数前的文件"""
        cutoff_time = datetime.now().timestamp() - (days_old * 24 * 60 * 60)
        deleted_files = []
        
        for filename in os.listdir(directory):
            filepath = os.path.join(directory, filename)
            if os.path.isfile(filepath):
                file_time = os.path.getmtime(filepath)
                if file_time < cutoff_time:
                    os.remove(filepath)
                    deleted_files.append(filename)
        
        return deleted_files

class ExcelExporter:
    """Excel导出工具类"""
    
    @staticmethod
    def export_to_excel(data, headers, filepath, sheet_name="Sheet1"):
        """
        导出数据到Excel文件
        
        Args:
            data: 数据列表（二维列表或元组）
            headers: 表头列表
            filepath: 保存路径
            sheet_name: 工作表名称
        """
        try:
            # 确保目录存在
            FileManager.ensure_directory(os.path.dirname(filepath))
            
            # 创建工作簿和工作表
            workbook = xlwt.Workbook(encoding='utf-8')
            sheet = workbook.add_sheet(sheet_name, cell_overwrite_ok=True)
            
            # 写入表头
            for col, header in enumerate(headers):
                sheet.write(0, col, header)
            
            # 写入数据
            for row, row_data in enumerate(data, 1):
                for col, cell_data in enumerate(row_data):
                    sheet.write(row, col, str(cell_data))
            
            # 保存文件
            workbook.save(filepath)
            return True, f"导出成功: {filepath}"
            
        except Exception as e:
            return False, f"导出失败: {str(e)}"
    
    @staticmethod
    def export_database_table(db_operations, table_name, filepath):
        """导出数据库表到Excel"""
        try:
            # 获取表数据
            data = db_operations.execute_query(f"SELECT * FROM {table_name}")
            # 获取表结构
            fields = db_operations.execute_query(f"DESCRIBE {table_name}")
            headers = [field[0] for field in fields]
            
            return ExcelExporter.export_to_excel(data, headers, filepath, table_name)
            
        except Exception as e:
            return False, f"导出数据库表失败: {str(e)}"

class ZipManager:
    """ZIP文件管理类"""
    
    @staticmethod
    def create_zip(source_paths, zip_path, include_base_dir=False):
        """
        创建ZIP压缩文件
        
        Args:
            source_paths: 源文件/目录路径列表
            zip_path: 目标ZIP文件路径
            include_base_dir: 是否包含基目录
        """
        try:
            with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                for source_path in source_paths:
                    if os.path.isfile(source_path):
                        # 处理单个文件
                        arcname = os.path.basename(source_path) if not include_base_dir else source_path
                        zipf.write(source_path, arcname)
                    elif os.path.isdir(source_path):
                        # 处理目录
                        for root, dirs, files in os.walk(source_path):
                            for file in files:
                                file_path = os.path.join(root, file)
                                if include_base_dir:
                                    arcname = file_path
                                else:
                                    arcname = os.path.relpath(file_path, os.path.dirname(source_path))
                                zipf.write(file_path, arcname)
            
            return True, f"ZIP文件创建成功: {zip_path}"
            
        except Exception as e:
            return False, f"创建ZIP文件失败: {str(e)}"
    
    @staticmethod
    def extract_zip(zip_path, extract_path):
        """解压ZIP文件"""
        try:
            FileManager.ensure_directory(extract_path)
            
            with zipfile.ZipFile(zip_path, 'r') as zipf:
                zipf.extractall(extract_path)
            
            return True, f"解压成功: {extract_path}"
            
        except Exception as e:
            return False, f"解压失败: {str(e)}"
    
    @staticmethod
    def zip_directory(directory_path, zip_path):
        """压缩整个目录"""
        return ZipManager.create_zip([directory_path], zip_path)

class BackupManager:
    """备份管理类"""
    
    @staticmethod
    def create_backup(backup_type="full"):
        """
        创建系统备份
        
        Args:
            backup_type: 备份类型 ("full", "database", "images", "config")
        """
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_dir = os.path.join(PATH_CONFIG['auto_login'], "backups")
        FileManager.ensure_directory(backup_dir)
        
        backup_files = []
        
        if backup_type in ["full", "database"]:
            # 备份数据库相关文件（这里可以扩展为实际数据库备份）
            db_backup_path = os.path.join(backup_dir, f"db_backup_{timestamp}.sql")
            # 这里可以添加数据库导出逻辑
            backup_files.append(db_backup_path)
        
        if backup_type in ["full", "images"]:
            # 备份图片文件
            images_zip = os.path.join(backup_dir, f"images_{timestamp}.zip")
            success, message = ZipManager.zip_directory(PATH_CONFIG['user_images'], images_zip)
            if success:
                backup_files.append(images_zip)
        
        if backup_type in ["full", "config"]:
            # 备份配置文件
            config_zip = os.path.join(backup_dir, f"config_{timestamp}.zip")
            config_files = [
                os.path.join(PATH_CONFIG['auto_login'], "login.pkl"),
                os.path.join(PATH_CONFIG['auto_login'], "auto.pkl"),
                os.path.join(PATH_CONFIG['auto_login'], "QMailSMTP.pkl")
            ]
            success, message = ZipManager.create_zip(config_files, config_zip)
            if success:
                backup_files.append(config_zip)
        
        return backup_files
    
    @staticmethod
    def cleanup_old_backups(keep_count=5):
        """清理旧的备份文件，只保留指定数量的最新备份"""
        backup_dir = os.path.join(PATH_CONFIG['auto_login'], "backups")
        if not os.path.exists(backup_dir):
            return
        
        backup_files = []
        for filename in os.listdir(backup_dir):
            if filename.endswith(('.zip', '.sql')):
                filepath = os.path.join(backup_dir, filename)
                backup_files.append((filepath, os.path.getmtime(filepath)))
        
        # 按修改时间排序
        backup_files.sort(key=lambda x: x[1], reverse=True)
        
        # 删除多余的备份文件
        deleted_files = []
        for filepath, _ in backup_files[keep_count:]:
            os.remove(filepath)
            deleted_files.append(os.path.basename(filepath))
        
        return deleted_files

class ImageManager:
    """图片管理类"""
    
    @staticmethod
    def compress_image(input_path, output_path, quality=85):
        """压缩图片"""
        try:
            from PIL import Image
            with Image.open(input_path) as img:
                img.save(output_path, quality=quality, optimize=True)
            return True
        except Exception as e:
            print(f"图片压缩失败: {e}")
            return False
    
    @staticmethod
    def resize_image(input_path, output_path, max_size=(800, 600)):
        """调整图片尺寸"""
        try:
            from PIL import Image
            with Image.open(input_path) as img:
                img.thumbnail(max_size, Image.Resampling.LANCZOS)
                img.save(output_path)
            return True
        except Exception as e:
            print(f"图片尺寸调整失败: {e}")
            return False
    
    @staticmethod
    def convert_to_grayscale(input_path, output_path):
        """转换为灰度图片"""
        try:
            from PIL import Image
            with Image.open(input_path) as img:
                gray_img = img.convert('L')
                gray_img.save(output_path)
            return True
        except Exception as e:
            print(f"图片灰度转换失败: {e}")
            return False
    
    @staticmethod
    def get_image_info(image_path):
        """获取图片信息"""
        try:
            from PIL import Image
            with Image.open(image_path) as img:
                info = {
                    'format': img.format,
                    'mode': img.mode,
                    'size': img.size,
                    'width': img.width,
                    'height': img.height
                }
                return info
        except Exception as e:
            print(f"获取图片信息失败: {e}")
            return None

class LogManager:
    """日志管理类"""
    
    @staticmethod
    def write_log(message, log_type="INFO", log_file="system.log"):
        """写入日志"""
        try:
            log_dir = os.path.join(PATH_CONFIG['auto_login'], "logs")
            FileManager.ensure_directory(log_dir)
            
            log_path = os.path.join(log_dir, log_file)
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            
            with open(log_path, 'a', encoding='utf-8') as f:
                f.write(f"[{timestamp}] [{log_type}] {message}\n")
            
            return True
        except Exception as e:
            print(f"写入日志失败: {e}")
            return False
    
    @staticmethod
    def read_log(log_file="system.log", lines=100):
        """读取日志"""
        try:
            log_dir = os.path.join(PATH_CONFIG['auto_login'], "logs")
            log_path = os.path.join(log_dir, log_file)
            
            if not os.path.exists(log_path):
                return []
            
            with open(log_path, 'r', encoding='utf-8') as f:
                all_lines = f.readlines()
                return all_lines[-lines:]
        except Exception as e:
            print(f"读取日志失败: {e}")
            return []

# 全局文件管理实例
file_manager = FileManager()
excel_exporter = ExcelExporter()
zip_manager = ZipManager()
backup_manager = BackupManager()
image_manager = ImageManager()
log_manager = LogManager()